1 The Big Picture of Statistical Inference

1.1 Core Philosophical Foundation

Statistical Inference: The process of using sample data to draw conclusions about a population or underlying process, while quantifying uncertainty.

The Fundamental Paradox: We use what is known (data) to learn about what is unknown (parameters/truth), accepting that our conclusions are probabilistic, not certain.

Analogy: You taste a spoonful of soup (sample) to infer if the whole pot (population) is well-seasoned. Inference is the formal, measurable version of this act.

2 The Two Pillars of Inference: Estimation & Testing

Think of these as answering two complementary questions about an unknown population parameter (e.g., mean μ, proportion p, effect size Δ).

# Create a simple visualization of the two pillars
pillars_data <- data.frame(
  Pillar = c("Estimation", "Hypothesis Testing"),
  Question = c("\n  \"What is it likely to be?\"", "\"Is there evidence for \n a specific claim?\""),
  Key_Product = c("Confidence Interval", "p-value"),
  Color = c("#3498db", "#e74c3c"),
  Height = c(1, 1)
)

ggplot(pillars_data, aes(x = Pillar, y = Height, fill = Pillar)) +
  geom_col(width = 0.8) +
  geom_text(aes(label = Question), vjust = 2, color = "white", size = 4.5, fontface = "bold") +
  geom_text(aes(label = Key_Product), vjust = -0.5, color = "black", size = 4) +
  scale_fill_manual(values = c("#3498db", "#e74c3c")) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.title = element_blank(),
    axis.text.y = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    plot.title = element_text(hjust = 0.5, size = 14)
  ) +
  ylim(0, 1.5) +
  labs(title = "The Two Pillars of Statistical Inference")

2.1 Pillar 1: Estimation — “What is it likely to be?”

  • Goal: Determine the plausible values for a parameter.
  • Key Product: An interval of plausible values.
  • Big-Picture Mindset: You are mapping the uncertainty terrain. You’re not picking one number as the “answer”; you’re defining a range where the truth likely resides.

2.2 Pillar 2: Hypothesis Testing — “Is there evidence for a specific claim?”

  • Goal: Evaluate the strength of evidence against a specific, default hypothesis.
  • Key Product: A probability (p-value) measuring compatibility between data and the null hypothesis.
  • Big-Picture Mindset: You are acting as a skeptical jury. The default (null) is innocence (no effect). The data must provide strong enough evidence to convict (reject the null).

3 Major Types & Real-World Use Cases

3.1 Confidence Intervals

  • What it is: A range of values, calculated from sample data, that is likely to contain the true population parameter a certain percentage of the time (e.g., 95%).

  • Big-Picture Interpretation: “If we were to repeat this study 100 times, about 95 of the resulting intervals would contain the true parameter. This specific interval is one of those attempts.”

set.seed(123)
# Simulate 20 confidence intervals
n_sim <- 20
n <- 30
true_mean <- 100
true_sd <- 15

ci_data <- data.frame(
  sim = 1:n_sim,
  mean = numeric(n_sim),
  lower = numeric(n_sim),
  upper = numeric(n_sim),
  contains_true = logical(n_sim)
)

for (i in 1:n_sim) {
  sample_data <- rnorm(n, mean = true_mean, sd = true_sd)
  test_result <- t.test(sample_data, conf.level = 0.95)
  ci_data$mean[i] <- mean(sample_data)
  ci_data$lower[i] <- test_result$conf.int[1]
  ci_data$upper[i] <- test_result$conf.int[2]
  ci_data$contains_true[i] <- (ci_data$lower[i] <= true_mean) & (ci_data$upper[i] >= true_mean)
}

ggplot(ci_data, aes(x = sim)) +
  geom_errorbar(aes(ymin = lower, ymax = upper, color = contains_true), 
                width = 0.3, size = 1) +
  geom_point(aes(y = mean), size = 2) +
  geom_hline(yintercept = true_mean, linetype = "dashed", color = "red", size = 1) +
  scale_color_manual(values = c("TRUE" = "darkgreen", "FALSE" = "darkred"),
                     labels = c("TRUE" = "Contains true mean", "FALSE" = "Does not contain true mean")) +
  labs(x = "Simulation Number", y = "Value", 
       title = "Simulation of 20 Confidence Intervals (95% level)",
       color = "Contains True Mean?") +
  theme_minimal() +
  theme(legend.position = "bottom")
Visualizing Confidence Intervals: 95% of intervals contain the true parameter (dashed line)

Visualizing Confidence Intervals: 95% of intervals contain the true parameter (dashed line)

Use-Case Examples

  1. Market Research: A survey finds 60% of a sample favor a new product. The 95% CI for the population proportion is [56%, 64%].

    # Example calculation for market research
    n <- 500  # sample size
    p_hat <- 0.60  # sample proportion
    margin_error <- 1.96 * sqrt(p_hat * (1 - p_hat) / n)
    ci_lower <- p_hat - margin_error
    ci_upper <- p_hat + margin_error
    
    cat(sprintf("Market Research Example:\n"),
    sprintf("Sample proportion: %.1f%%\n", p_hat * 100),
     sprintf("95%% Confidence Interval: [%.1f%%, %.1f%%]\n", 
                ci_lower * 100, ci_upper * 100),
     "\nInterpretation: We are 95%% confident that the true favorability\n",
     "among all customers is between ", round(ci_lower * 100, 1), 
        "% and ", round(ci_upper * 100, 1), "%.", sep = "")
    Market Research Example:
    Sample proportion: 60.0%
    95% Confidence Interval: [55.7%, 64.3%]
    
    Interpretation: We are 95%% confident that the true favorability
    among all customers is between 55.7% and 64.3%.

Interpretation: We are 95% confident that the true favorability among all customers is between 56% and 64%. This gives management a realistic range for planning.

  1. Medicine: A clinical trial finds a new drug reduces systolic blood pressure by an average of 12 mmHg, with a 95% CI of [8, 16] mmHg.

Interpretation: The true average effect for the population is likely between 8 and 16 mmHg. The interval provides both an estimate (12) and a measure of its precision.

3.2 Hypothesis Tests (The Decision Framework)

  • What it is: A formal procedure to decide between a null hypothesis (H₀)—often a statement of “no difference” or “no effect”—and an alternative hypothesis (H₁).

  • The Core Logic: Assume H₀ is true. Ask: “How surprising/unlikely is our observed sample data under this assumption?” This probability is the p-value. A very small p-value suggests the data is incompatible with H₀.

3.2.1 Use-Case Examples:

  1. Quality Control: A factory claims its bolts have a mean strength of 1000 psi. An auditor samples a batch.
    • H₀: μ = 1000 psi (process is on spec).
    • H₁: μ < 1000 psi (process is faulty).
      A very low p-value leads to rejecting H₀, triggering a machine recalibration.
  2. A/B Testing (Digital): Does a new webpage layout (B) have a higher click-through rate than the old one (A)?
    • H₀: p_B - p_A = 0 (no difference).
    • H₁: p_B - p_A > 0 (B is better).
      A p-value < a threshold (e.g., 0.05) provides statistical evidence to launch the new layout.
Hypothesis Testing Decision Flow

Hypothesis Testing Decision Flow

3.3 Regression Inference (Modeling Relationships)

  • What it is: Extends estimation and testing to the parameters of a model, most commonly examining the relationship between variables.

  • Big-Picture Mindset: You are determining which modeled relationships are meaningfully non-zero after accounting for random noise.

# Simulate regression data with confidence bands
set.seed(456)
n <- 100
x <- rnorm(n, mean = 50, sd = 15)
true_slope <- 2.5
true_intercept <- 10
y <- true_intercept + true_slope * x + rnorm(n, sd = 20)

# Fit linear model
model <- lm(y ~ x)

# Create prediction data
new_x <- seq(min(x), max(x), length.out = 100)
pred <- predict(model, newdata = data.frame(x = new_x), interval = "confidence")

# Plot
par(mfrow = c(1, 2))
# Plot 1: Data with regression line and CI
plot(x, y, pch = 19, col = rgb(0, 0, 1, 0.5), 
     main = "Regression with Confidence Band",
     xlab = "Predictor (X)", ylab = "Response (Y)")
lines(new_x, pred[, "fit"], col = "red", lwd = 2)
lines(new_x, pred[, "lwr"], col = "red", lty = 2)
lines(new_x, pred[, "upr"], col = "red", lty = 2)

# Plot 2: Coefficient estimate with CI
coef_est <- coef(model)[2]
coef_ci <- confint(model)[2,]

plot(1, coef_est, xlim = c(0.5, 1.5), ylim = c(coef_ci[1] - 0.5, coef_ci[2] + 0.5),
     pch = 19, cex = 1.5, col = "blue", xaxt = "n", xlab = "",
     ylab = "Slope Coefficient", main = "Coefficient Estimate with 95% CI",
     cex.main = 0.9)
segments(1, coef_ci[1], 1, coef_ci[2], lwd = 2)
abline(h = 0, lty = 3, col = "gray")
text(1, coef_est + 0.3, sprintf("%.2f", coef_est), pos = 3)
Regression Inference: Estimating relationships with uncertainty

Regression Inference: Estimating relationships with uncertainty

3.4 Use-Case Examples

  1. Economics: A regression models house price against square footage, bedrooms, and location.
    • Inference on the slope for square footage: A 95% CI tells us the likely dollar increase in price per extra sq. ft. A hypothesis test (p-value) tells us if we can confidently say the relationship isn’t zero.
Example Regression Output:
 =================================
 Coefficient for Square Footage:
   Estimate:  $150.25 per sq. ft.
   95% CI:    [$142.10, $158.40]
   p-value:   < 0.001
 
Interpretation: Each additional square foot is associated with
 an estimated $150 increase in price, and we are 95% confident
 the true increase is between $142 and $158.
  1. Public Health: A logistic regression studies risk factors for a disease. The inference on the odds ratio for smoking (e.g., OR = 2.5 with CI [2.1, 3.0]) allows us to state: Smoking is associated with 2.5 times the odds of disease, and we are confident the true increase is at least 2.1-fold.

3.5 Bayesian Inference (The Coherent Update)

  • What it is: A paradigm that combines prior knowledge/belief (prior distribution) with observed data (likelihood) to form an updated posterior distribution for a parameter.

  • Big-Picture Mindset: You treat parameters as probabilistic entities. You start with a prior (which can be objective or subjective), observe data, and rationally update your beliefs. The result is a full probability distribution for the parameter.

# Simulate Bayesian updating
set.seed(789)
x <- seq(0, 1, length.out = 100)

# Prior (moderately informed)
prior <- dbeta(x, 8, 8)

# Likelihood (data: 15 successes out of 20 trials)
a <- 15
b <- 5
likelihood <- dbeta(x, a, b)

# Posterior
posterior <- dbeta(x, 8 + a, 8 + b)

# Plot
plot_df <- data.frame(
  x = rep(x, 3),
  density = c(prior, likelihood, posterior),
  distribution = rep(c("Prior", "Likelihood (Data)", "Posterior"), each = length(x))
)

bayes <- ggplot(plot_df, aes(x = x, y = density, color = distribution, linetype = distribution)) +
  geom_line(size = 1.2) +
  scale_color_manual(values = c("Prior" = "blue", "Likelihood (Data)" = "steelblue", "Posterior" = "red")) +
  scale_linetype_manual(values = c("Prior" = "solid", "Likelihood (Data)" = "solid", "Posterior" = "solid")) +
  labs(x = "Parameter (e.g., success probability)", y = "Density",
       #title = "Bayesian Updating: Prior → Likelihood → Posterior",
       color = "Distribution", linetype = "Distribution") +
  theme(
  plot.margin = margin(t = 40, r = 20, b = 20, l = 20, unit = "pt"),
   plot.title = element_text(
    margin = margin(t = 20, b = 0)),  # Top and bottom margins
  axis.title.x = element_text(margin = margin(t = 10)),
  axis.title.y = element_text(margin = margin(r = 10))) +
  theme_minimal()
ggplotly(bayes)

Bayesian Inference: Updating Prior Belief with Data

3.5.1 Use-Case Examples:

  1. Drug Development: Early trials provide a prior on a drug’s efficacy. A larger Phase 3 trial provides data. Bayesian inference combines them to produce a posterior probability that the drug exceeds a minimum effectiveness threshold—a direct, intuitive statement for decision-makers.

  2. Machine Learning/Spam Filtering: The filter has a prior belief about the probability an email is spam. It updates this belief based on the data (presence of keywords like “free,” “winner”). The posterior probability dictates the “spam/not spam” classification.

4 Synthesis & Cautions

4.1 Key Relationships and Comparisons

Comparison of Statistical Inference Methods
Method Primary Question Main Output Interpretation
Confidence Intervals What is the plausible range? Interval estimate Long-run frequency of coverage
Hypothesis Tests Is there evidence against H₀? p-value, decision Probability of data if H₀ true
Regression Inference What is the relationship between variables? Parameter estimates with CIs Effect size with uncertainty
Bayesian Inference What should we believe given data and prior? Posterior distribution Degree of belief in parameter values
  • Estimation (CI) and Testing (p-values) are linked: A 95% CI that excludes a null value (like 0) corresponds to a hypothesis test rejecting H₀ at α=0.05.
# Demonstrate relationship between CI and hypothesis test


# Simulate data where CI excludes 0
set.seed(321)
sample_data <- rnorm(50, mean = 1.5, sd = 2)

# T-test
test_result <- t.test(sample_data, mu = 0)
ci <- test_result$conf.int

cat("  Demonstration: Relationship between CI and Hypothesis Test\n",
"==========================================================\n",
sprintf("\n  Sample mean: %.3f\n", mean(sample_data)),
sprintf("95%% Confidence Interval: [%.3f, %.3f]\n", ci[1], ci[2]),
sprintf("p-value for H₀: μ = 0: %.4f\n", test_result$p.value),
sprintf("\n we %s the null hypothesis at α=0.05.\n", 
            ifelse(test_result$p.value < 0.05, "REJECT", "FAIL TO REJECT")))
  Demonstration: Relationship between CI and Hypothesis Test
 ==========================================================
 
  Sample mean: 1.659
 95% Confidence Interval: [1.116, 2.202]
 p-value for H₀: μ = 0: 0.0000
 
 we REJECT the null hypothesis at α=0.05.
  • Statistical vs. Practical Significance: A test can find a tiny, statistically significant effect (due to huge sample size), but it may be practically meaningless. Always look at the estimated effect size and its CI.

  • Inference Requires Representative Data: Garbage in, garbage out. Biased sampling invalidates any inference, no matter how sophisticated.

  • Frequentist (CI/Tests) vs. Bayesian Mindset:

    • Frequentist: Probability = long-run frequency. Parameters are fixed, data is random.
    • Bayesian: Probability = degree of belief. Parameters are random, data is fixed.
      Both are powerful tools; the choice often depends on the question, field, and availability of prior information.

5 Key Takeaway

Statistical inference is the science of disciplined learning from data in the face of uncertainty. It moves us from simply describing our sample (“The average in our data was 10”) to making generalizable statements with quantified uncertainty (“We are 95% confident the population average is between 9 and 11”).

Mastering the big picture allows you to choose the right tool for the question at hand, from estimating a market size, to testing a new medical treatment, to updating a recommendation algorithm.

The Inference Process: From Data to Knowledge

The Inference Process: From Data to Knowledge

6 Further Resources

  • R Packages for Inference:

    • Basic: stats (base R), infer (tidyverse approach)
    • Bayesian: rstan, brms, rstanarm
    • Specialized: survival, lme4, mgcv
  • Practice with: infer::generate(), infer::calculate() for simulation-based inference

  • Next Steps: Experimental design, power analysis, multiple testing corrections, causal inference frameworks.

Remember: The map is not the territory. Statistical models are simplified representations of reality—powerful, but always imperfect.

LS0tDQp0aXRsZTogIkFuIE92ZXJ2aWV3IG9mIFN0YXRpc3RpY2FsIEluZmVyZW5jZXMiDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCmlmICghcmVxdWlyZSgiZml0ZGlzdHJwbHVzIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZml0ZGlzdHJwbHVzIikNCiAgbGlicmFyeShmaXRkaXN0cnBsdXMpDQp9DQojIyBsaWJyYXJ5KGZpdGRpc3RycGx1cykNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQoNClwNCg0KIyBUaGUgQmlnIFBpY3R1cmUgb2YgU3RhdGlzdGljYWwgSW5mZXJlbmNlDQoNCiMjIENvcmUgUGhpbG9zb3BoaWNhbCBGb3VuZGF0aW9uDQoNCioqU3RhdGlzdGljYWwgSW5mZXJlbmNlOioqIFRoZSBwcm9jZXNzIG9mIHVzaW5nICoqc2FtcGxlIGRhdGEqKiB0byBkcmF3IGNvbmNsdXNpb25zIGFib3V0IGEgKipwb3B1bGF0aW9uKiogb3IgdW5kZXJseWluZyBwcm9jZXNzLCB3aGlsZSAqKnF1YW50aWZ5aW5nIHVuY2VydGFpbnR5KiouDQoNCioqVGhlIEZ1bmRhbWVudGFsIFBhcmFkb3g6KiogV2UgdXNlIHdoYXQgaXMga25vd24gKGRhdGEpIHRvIGxlYXJuIGFib3V0IHdoYXQgaXMgdW5rbm93biAocGFyYW1ldGVycy90cnV0aCksIGFjY2VwdGluZyB0aGF0IG91ciBjb25jbHVzaW9ucyBhcmUgcHJvYmFiaWxpc3RpYywgbm90IGNlcnRhaW4uDQoNCj4gKipBbmFsb2d5OioqIFlvdSB0YXN0ZSBhIHNwb29uZnVsIG9mIHNvdXAgKHNhbXBsZSkgdG8gaW5mZXIgaWYgdGhlIHdob2xlIHBvdCAocG9wdWxhdGlvbikgaXMgd2VsbC1zZWFzb25lZC4gSW5mZXJlbmNlIGlzIHRoZSBmb3JtYWwsIG1lYXN1cmFibGUgdmVyc2lvbiBvZiB0aGlzIGFjdC4NCg0KDQoNCiMgVGhlIFR3byBQaWxsYXJzIG9mIEluZmVyZW5jZTogRXN0aW1hdGlvbiAmIFRlc3RpbmcNCg0KVGhpbmsgb2YgdGhlc2UgYXMgYW5zd2VyaW5nIHR3byBjb21wbGVtZW50YXJ5IHF1ZXN0aW9ucyBhYm91dCBhbiB1bmtub3duIHBvcHVsYXRpb24gcGFyYW1ldGVyIChlLmcuLCBtZWFuIM68LCBwcm9wb3J0aW9uIHAsIGVmZmVjdCBzaXplIM6UKS4NCg0KYGBge3IgcGlsbGFycy1kaWFncmFtLCBmaWcuY2FwPSIiLCBvdXQud2lkdGg9IjgwJSJ9DQojIENyZWF0ZSBhIHNpbXBsZSB2aXN1YWxpemF0aW9uIG9mIHRoZSB0d28gcGlsbGFycw0KcGlsbGFyc19kYXRhIDwtIGRhdGEuZnJhbWUoDQogIFBpbGxhciA9IGMoIkVzdGltYXRpb24iLCAiSHlwb3RoZXNpcyBUZXN0aW5nIiksDQogIFF1ZXN0aW9uID0gYygiXG4gIFwiV2hhdCBpcyBpdCBsaWtlbHkgdG8gYmU/XCIiLCAiXCJJcyB0aGVyZSBldmlkZW5jZSBmb3IgXG4gYSBzcGVjaWZpYyBjbGFpbT9cIiIpLA0KICBLZXlfUHJvZHVjdCA9IGMoIkNvbmZpZGVuY2UgSW50ZXJ2YWwiLCAicC12YWx1ZSIpLA0KICBDb2xvciA9IGMoIiMzNDk4ZGIiLCAiI2U3NGMzYyIpLA0KICBIZWlnaHQgPSBjKDEsIDEpDQopDQoNCmdncGxvdChwaWxsYXJzX2RhdGEsIGFlcyh4ID0gUGlsbGFyLCB5ID0gSGVpZ2h0LCBmaWxsID0gUGlsbGFyKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuOCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUXVlc3Rpb24pLCB2anVzdCA9IDIsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDQuNSwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEtleV9Qcm9kdWN0KSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSA0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMzNDk4ZGIiLCAiI2U3NGMzYyIpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpDQogICkgKw0KICB5bGltKDAsIDEuNSkgKw0KICBsYWJzKHRpdGxlID0gIlRoZSBUd28gUGlsbGFycyBvZiBTdGF0aXN0aWNhbCBJbmZlcmVuY2UiKQ0KYGBgDQoNCiMjIFBpbGxhciAxOiBFc3RpbWF0aW9uIOKAlCAiV2hhdCBpcyBpdCBsaWtlbHkgdG8gYmU/Ig0KDQoqICoqR29hbDoqKiBEZXRlcm1pbmUgdGhlIHBsYXVzaWJsZSB2YWx1ZXMgZm9yIGEgcGFyYW1ldGVyLg0KKiAqKktleSBQcm9kdWN0OioqIEFuICoqaW50ZXJ2YWwqKiBvZiBwbGF1c2libGUgdmFsdWVzLg0KKiAqKkJpZy1QaWN0dXJlIE1pbmRzZXQ6KiogWW91IGFyZSBtYXBwaW5nIHRoZSAqKnVuY2VydGFpbnR5IHRlcnJhaW4qKi4gWW91J3JlIG5vdCBwaWNraW5nIG9uZSBudW1iZXIgYXMgdGhlICJhbnN3ZXIiOyB5b3UncmUgZGVmaW5pbmcgYSByYW5nZSB3aGVyZSB0aGUgdHJ1dGggbGlrZWx5IHJlc2lkZXMuDQoNCg0KIyMgUGlsbGFyIDI6IEh5cG90aGVzaXMgVGVzdGluZyDigJQgIklzIHRoZXJlIGV2aWRlbmNlIGZvciBhIHNwZWNpZmljIGNsYWltPyINCg0KKiAqKkdvYWw6KiogRXZhbHVhdGUgdGhlIHN0cmVuZ3RoIG9mIGV2aWRlbmNlICphZ2FpbnN0KiBhIHNwZWNpZmljLCBkZWZhdWx0IGh5cG90aGVzaXMuDQoqICoqS2V5IFByb2R1Y3Q6KiogQSAqKnByb2JhYmlsaXR5IChwLXZhbHVlKSoqIG1lYXN1cmluZyBjb21wYXRpYmlsaXR5IGJldHdlZW4gZGF0YSBhbmQgdGhlIG51bGwgaHlwb3RoZXNpcy4NCiogKipCaWctUGljdHVyZSBNaW5kc2V0OioqIFlvdSBhcmUgYWN0aW5nIGFzIGEgKipza2VwdGljYWwganVyeSoqLiBUaGUgZGVmYXVsdCAobnVsbCkgaXMgaW5ub2NlbmNlIChubyBlZmZlY3QpLiBUaGUgZGF0YSBtdXN0IHByb3ZpZGUgc3Ryb25nIGVub3VnaCBldmlkZW5jZSB0byBjb252aWN0IChyZWplY3QgdGhlIG51bGwpLg0KDQoNCiMgTWFqb3IgVHlwZXMgJiBSZWFsLVdvcmxkIFVzZSBDYXNlcw0KDQojIyBDb25maWRlbmNlIEludGVydmFscyANCg0KKiAqKldoYXQgaXQgaXM6KiogQSByYW5nZSBvZiB2YWx1ZXMsIGNhbGN1bGF0ZWQgZnJvbSBzYW1wbGUgZGF0YSwgdGhhdCBpcyBsaWtlbHkgdG8gY29udGFpbiB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHBhcmFtZXRlciBhIGNlcnRhaW4gcGVyY2VudGFnZSBvZiB0aGUgdGltZSAoZS5nLiwgOTUlKS4NCg0KKiAqKkJpZy1QaWN0dXJlIEludGVycHJldGF0aW9uOioqICJJZiB3ZSB3ZXJlIHRvIHJlcGVhdCB0aGlzIHN0dWR5IDEwMCB0aW1lcywgYWJvdXQgOTUgb2YgdGhlIHJlc3VsdGluZyBpbnRlcnZhbHMgd291bGQgY29udGFpbiB0aGUgdHJ1ZSBwYXJhbWV0ZXIuIFRoaXMgc3BlY2lmaWMgaW50ZXJ2YWwgaXMgb25lIG9mIHRob3NlIGF0dGVtcHRzLiINCg0KYGBge3IgY29uZmlkZW5jZS1pbnRlcnZhbC1kZW1vLCBmaWcuY2FwPSJWaXN1YWxpemluZyBDb25maWRlbmNlIEludGVydmFsczogOTUlIG9mIGludGVydmFscyBjb250YWluIHRoZSB0cnVlIHBhcmFtZXRlciAoZGFzaGVkIGxpbmUpIn0NCnNldC5zZWVkKDEyMykNCiMgU2ltdWxhdGUgMjAgY29uZmlkZW5jZSBpbnRlcnZhbHMNCm5fc2ltIDwtIDIwDQpuIDwtIDMwDQp0cnVlX21lYW4gPC0gMTAwDQp0cnVlX3NkIDwtIDE1DQoNCmNpX2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgc2ltID0gMTpuX3NpbSwNCiAgbWVhbiA9IG51bWVyaWMobl9zaW0pLA0KICBsb3dlciA9IG51bWVyaWMobl9zaW0pLA0KICB1cHBlciA9IG51bWVyaWMobl9zaW0pLA0KICBjb250YWluc190cnVlID0gbG9naWNhbChuX3NpbSkNCikNCg0KZm9yIChpIGluIDE6bl9zaW0pIHsNCiAgc2FtcGxlX2RhdGEgPC0gcm5vcm0obiwgbWVhbiA9IHRydWVfbWVhbiwgc2QgPSB0cnVlX3NkKQ0KICB0ZXN0X3Jlc3VsdCA8LSB0LnRlc3Qoc2FtcGxlX2RhdGEsIGNvbmYubGV2ZWwgPSAwLjk1KQ0KICBjaV9kYXRhJG1lYW5baV0gPC0gbWVhbihzYW1wbGVfZGF0YSkNCiAgY2lfZGF0YSRsb3dlcltpXSA8LSB0ZXN0X3Jlc3VsdCRjb25mLmludFsxXQ0KICBjaV9kYXRhJHVwcGVyW2ldIDwtIHRlc3RfcmVzdWx0JGNvbmYuaW50WzJdDQogIGNpX2RhdGEkY29udGFpbnNfdHJ1ZVtpXSA8LSAoY2lfZGF0YSRsb3dlcltpXSA8PSB0cnVlX21lYW4pICYgKGNpX2RhdGEkdXBwZXJbaV0gPj0gdHJ1ZV9tZWFuKQ0KfQ0KDQpnZ3Bsb3QoY2lfZGF0YSwgYWVzKHggPSBzaW0pKSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBsb3dlciwgeW1heCA9IHVwcGVyLCBjb2xvciA9IGNvbnRhaW5zX3RydWUpLCANCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMywgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoeSA9IG1lYW4pLCBzaXplID0gMikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0cnVlX21lYW4sIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIsIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJUUlVFIiA9ICJkYXJrZ3JlZW4iLCAiRkFMU0UiID0gImRhcmtyZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlRSVUUiID0gIkNvbnRhaW5zIHRydWUgbWVhbiIsICJGQUxTRSIgPSAiRG9lcyBub3QgY29udGFpbiB0cnVlIG1lYW4iKSkgKw0KICBsYWJzKHggPSAiU2ltdWxhdGlvbiBOdW1iZXIiLCB5ID0gIlZhbHVlIiwgDQogICAgICAgdGl0bGUgPSAiU2ltdWxhdGlvbiBvZiAyMCBDb25maWRlbmNlIEludGVydmFscyAoOTUlIGxldmVsKSIsDQogICAgICAgY29sb3IgPSAiQ29udGFpbnMgVHJ1ZSBNZWFuPyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KKipVc2UtQ2FzZSBFeGFtcGxlcyoqDQoNCjEuICAqKk1hcmtldCBSZXNlYXJjaDoqKiBBIHN1cnZleSBmaW5kcyA2MCUgb2YgYSBzYW1wbGUgZmF2b3IgYSBuZXcgcHJvZHVjdC4gVGhlICoqOTUlIENJIGZvciB0aGUgcG9wdWxhdGlvbiBwcm9wb3J0aW9uKiogaXMgWzU2JSwgNjQlXS4gDQogICAgDQogICAgYGBge3IgbWFya2V0LXJlc2VhcmNoLWV4YW1wbGV9DQogICAgIyBFeGFtcGxlIGNhbGN1bGF0aW9uIGZvciBtYXJrZXQgcmVzZWFyY2gNCiAgICBuIDwtIDUwMCAgIyBzYW1wbGUgc2l6ZQ0KICAgIHBfaGF0IDwtIDAuNjAgICMgc2FtcGxlIHByb3BvcnRpb24NCiAgICBtYXJnaW5fZXJyb3IgPC0gMS45NiAqIHNxcnQocF9oYXQgKiAoMSAtIHBfaGF0KSAvIG4pDQogICAgY2lfbG93ZXIgPC0gcF9oYXQgLSBtYXJnaW5fZXJyb3INCiAgICBjaV91cHBlciA8LSBwX2hhdCArIG1hcmdpbl9lcnJvcg0KICAgIA0KICAgIGNhdChzcHJpbnRmKCJNYXJrZXQgUmVzZWFyY2ggRXhhbXBsZTpcbiIpLA0KICAgIHNwcmludGYoIlNhbXBsZSBwcm9wb3J0aW9uOiAlLjFmJSVcbiIsIHBfaGF0ICogMTAwKSwNCiAgICAgc3ByaW50ZigiOTUlJSBDb25maWRlbmNlIEludGVydmFsOiBbJS4xZiUlLCAlLjFmJSVdXG4iLCANCiAgICAgICAgICAgICAgICBjaV9sb3dlciAqIDEwMCwgY2lfdXBwZXIgKiAxMDApLA0KICAgICAiXG5JbnRlcnByZXRhdGlvbjogV2UgYXJlIDk1JSUgY29uZmlkZW50IHRoYXQgdGhlIHRydWUgZmF2b3JhYmlsaXR5XG4iLA0KICAgICAiYW1vbmcgYWxsIGN1c3RvbWVycyBpcyBiZXR3ZWVuICIsIHJvdW5kKGNpX2xvd2VyICogMTAwLCAxKSwgDQogICAgICAgICIlIGFuZCAiLCByb3VuZChjaV91cHBlciAqIDEwMCwgMSksICIlLiIsIHNlcCA9ICIiKQ0KICAgIGBgYA0KICAgIA0KKkludGVycHJldGF0aW9uOiogV2UgYXJlIDk1JSBjb25maWRlbnQgdGhhdCB0aGUgdHJ1ZSBmYXZvcmFiaWxpdHkgYW1vbmcgYWxsIGN1c3RvbWVycyBpcyBiZXR3ZWVuIDU2JSBhbmQgNjQlLiBUaGlzIGdpdmVzIG1hbmFnZW1lbnQgYSByZWFsaXN0aWMgcmFuZ2UgZm9yIHBsYW5uaW5nLg0KDQoyLiAqKk1lZGljaW5lOioqIEEgY2xpbmljYWwgdHJpYWwgZmluZHMgYSBuZXcgZHJ1ZyByZWR1Y2VzIHN5c3RvbGljIGJsb29kIHByZXNzdXJlIGJ5IGFuIGF2ZXJhZ2Ugb2YgMTIgbW1IZywgd2l0aCBhICoqOTUlIENJIG9mIFs4LCAxNl0gbW1IZyoqLiANCg0KKkludGVycHJldGF0aW9uOiogVGhlIHRydWUgYXZlcmFnZSBlZmZlY3QgZm9yIHRoZSBwb3B1bGF0aW9uIGlzIGxpa2VseSBiZXR3ZWVuIDggYW5kIDE2IG1tSGcuIFRoZSBpbnRlcnZhbCBwcm92aWRlcyBib3RoIGFuIGVzdGltYXRlICgxMikgYW5kIGEgbWVhc3VyZSBvZiBpdHMgcHJlY2lzaW9uLg0KDQojIyBIeXBvdGhlc2lzIFRlc3RzIChUaGUgRGVjaXNpb24gRnJhbWV3b3JrKQ0KDQoqICoqV2hhdCBpdCBpczoqKiBBIGZvcm1hbCBwcm9jZWR1cmUgdG8gZGVjaWRlIGJldHdlZW4gYSAqKm51bGwgaHlwb3RoZXNpcyAoSOKCgCkqKuKAlG9mdGVuIGEgc3RhdGVtZW50IG9mICJubyBkaWZmZXJlbmNlIiBvciAibm8gZWZmZWN0IuKAlGFuZCBhbiAqKmFsdGVybmF0aXZlIGh5cG90aGVzaXMgKEjigoEpKiouDQoNCiogKipUaGUgQ29yZSBMb2dpYzoqKiBBc3N1bWUgSOKCgCBpcyB0cnVlLiBBc2s6ICJIb3cgc3VycHJpc2luZy91bmxpa2VseSBpcyBvdXIgb2JzZXJ2ZWQgc2FtcGxlIGRhdGEgdW5kZXIgdGhpcyBhc3N1bXB0aW9uPyIgVGhpcyBwcm9iYWJpbGl0eSBpcyB0aGUgKipwLXZhbHVlKiouIEEgdmVyeSBzbWFsbCBwLXZhbHVlIHN1Z2dlc3RzIHRoZSBkYXRhIGlzIGluY29tcGF0aWJsZSB3aXRoIEjigoAuDQoNCiMjIyAqKlVzZS1DYXNlIEV4YW1wbGVzOioqDQoNCjEuICAqKlF1YWxpdHkgQ29udHJvbDoqKiBBIGZhY3RvcnkgY2xhaW1zIGl0cyBib2x0cyBoYXZlIGEgbWVhbiBzdHJlbmd0aCBvZiAxMDAwIHBzaS4gQW4gYXVkaXRvciBzYW1wbGVzIGEgYmF0Y2guICANCiAgICAqICAgKipI4oKAOioqIM68ID0gMTAwMCBwc2kgKHByb2Nlc3MgaXMgb24gc3BlYykuICANCiAgICAqICAgKipI4oKBOioqIM68IDwgMTAwMCBwc2kgKHByb2Nlc3MgaXMgZmF1bHR5KS4gIA0KICAgIEEgdmVyeSBsb3cgcC12YWx1ZSBsZWFkcyB0byAqKnJlamVjdGluZyBI4oKAKiosIHRyaWdnZXJpbmcgYSBtYWNoaW5lIHJlY2FsaWJyYXRpb24uDQoNCjIuICAqKkEvQiBUZXN0aW5nIChEaWdpdGFsKToqKiBEb2VzIGEgbmV3IHdlYnBhZ2UgbGF5b3V0IChCKSBoYXZlIGEgaGlnaGVyIGNsaWNrLXRocm91Z2ggcmF0ZSB0aGFuIHRoZSBvbGQgb25lIChBKT8gIA0KICAgICogICAqKkjigoA6KiogcF9CIC0gcF9BID0gMCAobm8gZGlmZmVyZW5jZSkuICANCiAgICAqICAgKipI4oKBOioqIHBfQiAtIHBfQSA+IDAgKEIgaXMgYmV0dGVyKS4gIA0KICAgIEEgcC12YWx1ZSA8IGEgdGhyZXNob2xkIChlLmcuLCAwLjA1KSBwcm92aWRlcyBzdGF0aXN0aWNhbCBldmlkZW5jZSB0byAqKmxhdW5jaCB0aGUgbmV3IGxheW91dCoqLg0KDQpgYGB7ciBoeXBvdGhlc2lzLXRlc3QtZmxvdywgZmlnLmNhcD0iSHlwb3RoZXNpcyBUZXN0aW5nIERlY2lzaW9uIEZsb3ciLCBlY2hvPUZBTFNFfQ0KIyBDcmVhdGUgYSBmbG93Y2hhcnQtbGlrZSB2aXN1YWxpemF0aW9uDQpmbG93X2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgc3RlcCA9IGMoIjEuIFN0YXRlIEh5cG90aGVzZXMiLCANCiAgICAgICAgICAgIjIuIENvbGxlY3QgRGF0YSIsIA0KICAgICAgICAgICAiMy4gQ2FsY3VsYXRlIFN0YXRpc3RpYyIsIA0KICAgICAgICAgICAiNC4gQ29tcHV0ZSBwLXZhbHVlIiwNCiAgICAgICAgICAgIjUuIE1ha2UgRGVjaXNpb24iKSwNCiAgeCA9IDE6NSwNCiAgeSA9IHJlcCgxLCA1KQ0KKQ0KDQpnZ3Bsb3QoZmxvd19kYXRhLCBhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSA0MCwgY29sb3IgPSAiIzJjM2U1MCIsIGFscGhhID0gMC43KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzdGVwKSwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMykgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSB4Ky40NSwgeGVuZCA9IHggKyAuNTYsIHkgPSB5LCB5ZW5kID0geSksIA0KICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMSwgImNtIikpLCANCiAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBzaXplID0gMSkgKw0KICB4bGltKDAuNSwgNS41KSArDQogIHlsaW0oMC44LCAxLjIpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgbGFicyh0aXRsZSA9ICJIeXBvdGhlc2lzIFRlc3RpbmcgUHJvY2VzcyBGbG93IikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpKQ0KYGBgDQoNCiMjIFJlZ3Jlc3Npb24gSW5mZXJlbmNlIChNb2RlbGluZyBSZWxhdGlvbnNoaXBzKQ0KDQoqICoqV2hhdCBpdCBpczoqKiBFeHRlbmRzIGVzdGltYXRpb24gYW5kIHRlc3RpbmcgdG8gdGhlIHBhcmFtZXRlcnMgb2YgYSAqKm1vZGVsKiosIG1vc3QgY29tbW9ubHkgZXhhbWluaW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2YXJpYWJsZXMuDQoNCiogKipCaWctUGljdHVyZSBNaW5kc2V0OioqIFlvdSBhcmUgZGV0ZXJtaW5pbmcgd2hpY2ggbW9kZWxlZCByZWxhdGlvbnNoaXBzIGFyZSAqKm1lYW5pbmdmdWxseSBub24temVybyoqIGFmdGVyIGFjY291bnRpbmcgZm9yIHJhbmRvbSBub2lzZS4NCg0KYGBge3IgcmVncmVzc2lvbi1leGFtcGxlLCBmaWcuY2FwPSJSZWdyZXNzaW9uIEluZmVyZW5jZTogRXN0aW1hdGluZyByZWxhdGlvbnNoaXBzIHdpdGggdW5jZXJ0YWludHkiLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00fQ0KIyBTaW11bGF0ZSByZWdyZXNzaW9uIGRhdGEgd2l0aCBjb25maWRlbmNlIGJhbmRzDQpzZXQuc2VlZCg0NTYpDQpuIDwtIDEwMA0KeCA8LSBybm9ybShuLCBtZWFuID0gNTAsIHNkID0gMTUpDQp0cnVlX3Nsb3BlIDwtIDIuNQ0KdHJ1ZV9pbnRlcmNlcHQgPC0gMTANCnkgPC0gdHJ1ZV9pbnRlcmNlcHQgKyB0cnVlX3Nsb3BlICogeCArIHJub3JtKG4sIHNkID0gMjApDQoNCiMgRml0IGxpbmVhciBtb2RlbA0KbW9kZWwgPC0gbG0oeSB+IHgpDQoNCiMgQ3JlYXRlIHByZWRpY3Rpb24gZGF0YQ0KbmV3X3ggPC0gc2VxKG1pbih4KSwgbWF4KHgpLCBsZW5ndGgub3V0ID0gMTAwKQ0KcHJlZCA8LSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gZGF0YS5mcmFtZSh4ID0gbmV3X3gpLCBpbnRlcnZhbCA9ICJjb25maWRlbmNlIikNCg0KIyBQbG90DQpwYXIobWZyb3cgPSBjKDEsIDIpKQ0KIyBQbG90IDE6IERhdGEgd2l0aCByZWdyZXNzaW9uIGxpbmUgYW5kIENJDQpwbG90KHgsIHksIHBjaCA9IDE5LCBjb2wgPSByZ2IoMCwgMCwgMSwgMC41KSwgDQogICAgIG1haW4gPSAiUmVncmVzc2lvbiB3aXRoIENvbmZpZGVuY2UgQmFuZCIsDQogICAgIHhsYWIgPSAiUHJlZGljdG9yIChYKSIsIHlsYWIgPSAiUmVzcG9uc2UgKFkpIikNCmxpbmVzKG5ld194LCBwcmVkWywgImZpdCJdLCBjb2wgPSAicmVkIiwgbHdkID0gMikNCmxpbmVzKG5ld194LCBwcmVkWywgImx3ciJdLCBjb2wgPSAicmVkIiwgbHR5ID0gMikNCmxpbmVzKG5ld194LCBwcmVkWywgInVwciJdLCBjb2wgPSAicmVkIiwgbHR5ID0gMikNCg0KIyBQbG90IDI6IENvZWZmaWNpZW50IGVzdGltYXRlIHdpdGggQ0kNCmNvZWZfZXN0IDwtIGNvZWYobW9kZWwpWzJdDQpjb2VmX2NpIDwtIGNvbmZpbnQobW9kZWwpWzIsXQ0KDQpwbG90KDEsIGNvZWZfZXN0LCB4bGltID0gYygwLjUsIDEuNSksIHlsaW0gPSBjKGNvZWZfY2lbMV0gLSAwLjUsIGNvZWZfY2lbMl0gKyAwLjUpLA0KICAgICBwY2ggPSAxOSwgY2V4ID0gMS41LCBjb2wgPSAiYmx1ZSIsIHhheHQgPSAibiIsIHhsYWIgPSAiIiwNCiAgICAgeWxhYiA9ICJTbG9wZSBDb2VmZmljaWVudCIsIG1haW4gPSAiQ29lZmZpY2llbnQgRXN0aW1hdGUgd2l0aCA5NSUgQ0kiLA0KICAgICBjZXgubWFpbiA9IDAuOSkNCnNlZ21lbnRzKDEsIGNvZWZfY2lbMV0sIDEsIGNvZWZfY2lbMl0sIGx3ZCA9IDIpDQphYmxpbmUoaCA9IDAsIGx0eSA9IDMsIGNvbCA9ICJncmF5IikNCnRleHQoMSwgY29lZl9lc3QgKyAwLjMsIHNwcmludGYoIiUuMmYiLCBjb2VmX2VzdCksIHBvcyA9IDMpDQpgYGANCg0KIyMgVXNlLUNhc2UgRXhhbXBsZXMNCg0KMS4gICoqRWNvbm9taWNzOioqIEEgcmVncmVzc2lvbiBtb2RlbHMgaG91c2UgcHJpY2UgYWdhaW5zdCBzcXVhcmUgZm9vdGFnZSwgYmVkcm9vbXMsIGFuZCBsb2NhdGlvbi4gIA0KICAgICogICAqKkluZmVyZW5jZSBvbiB0aGUgc2xvcGUgZm9yIHNxdWFyZSBmb290YWdlOioqIEEgOTUlIENJIHRlbGxzIHVzIHRoZSBsaWtlbHkgZG9sbGFyIGluY3JlYXNlIGluIHByaWNlIHBlciBleHRyYSBzcS4gZnQuIEEgaHlwb3RoZXNpcyB0ZXN0IChwLXZhbHVlKSB0ZWxscyB1cyBpZiB3ZSBjYW4gY29uZmlkZW50bHkgc2F5IHRoZSByZWxhdGlvbnNoaXAgaXNuJ3QgemVyby4NCg0KYGBge3IgcmVncmVzc2lvbi1vdXRwdXQtZXhhbXBsZSwgZWNobz1GQUxTRX0NCiMgRGlzcGxheSBzYW1wbGUgcmVncmVzc2lvbiBvdXRwdXQNCmNhdCgiRXhhbXBsZSBSZWdyZXNzaW9uIE91dHB1dDpcbiIsDQogIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwNCiAiQ29lZmZpY2llbnQgZm9yIFNxdWFyZSBGb290YWdlOlxuIiwNCiAiICBFc3RpbWF0ZTogICQxNTAuMjUgcGVyIHNxLiBmdC5cbiIsDQogIiAgOTUlIENJOiAgICBbJDE0Mi4xMCwgJDE1OC40MF1cbiIsDQogIiAgcC12YWx1ZTogICA8IDAuMDAxXG4iLA0KICJcbkludGVycHJldGF0aW9uOiBFYWNoIGFkZGl0aW9uYWwgc3F1YXJlIGZvb3QgaXMgYXNzb2NpYXRlZCB3aXRoXG4iLA0KICJhbiBlc3RpbWF0ZWQgJDE1MCBpbmNyZWFzZSBpbiBwcmljZSwgYW5kIHdlIGFyZSA5NSUgY29uZmlkZW50XG4iLA0KICJ0aGUgdHJ1ZSBpbmNyZWFzZSBpcyBiZXR3ZWVuICQxNDIgYW5kICQxNTguXG4iKQ0KYGBgDQoNCjIuICAqKlB1YmxpYyBIZWFsdGg6KiogQSBsb2dpc3RpYyByZWdyZXNzaW9uIHN0dWRpZXMgcmlzayBmYWN0b3JzIGZvciBhIGRpc2Vhc2UuIFRoZSAqKmluZmVyZW5jZSBvbiB0aGUgb2RkcyByYXRpbyBmb3Igc21va2luZyoqIChlLmcuLCBPUiA9IDIuNSB3aXRoIENJIFsyLjEsIDMuMF0pIGFsbG93cyB1cyB0byBzdGF0ZTogU21va2luZyBpcyBhc3NvY2lhdGVkIHdpdGggMi41IHRpbWVzIHRoZSBvZGRzIG9mIGRpc2Vhc2UsIGFuZCB3ZSBhcmUgY29uZmlkZW50IHRoZSB0cnVlIGluY3JlYXNlIGlzIGF0IGxlYXN0IDIuMS1mb2xkLg0KDQoNCiMjIEJheWVzaWFuIEluZmVyZW5jZSAoVGhlIENvaGVyZW50IFVwZGF0ZSkNCg0KKiAqKldoYXQgaXQgaXM6KiogQSBwYXJhZGlnbSB0aGF0ICoqY29tYmluZXMgcHJpb3Iga25vd2xlZGdlL2JlbGllZioqIChwcmlvciBkaXN0cmlidXRpb24pIHdpdGggKipvYnNlcnZlZCBkYXRhKiogKGxpa2VsaWhvb2QpIHRvIGZvcm0gYW4gdXBkYXRlZCAqKnBvc3RlcmlvciBkaXN0cmlidXRpb24qKiBmb3IgYSBwYXJhbWV0ZXIuDQoNCiogKipCaWctUGljdHVyZSBNaW5kc2V0OioqIFlvdSB0cmVhdCBwYXJhbWV0ZXJzIGFzIHByb2JhYmlsaXN0aWMgZW50aXRpZXMuIFlvdSBzdGFydCB3aXRoIGEgcHJpb3IgKHdoaWNoIGNhbiBiZSBvYmplY3RpdmUgb3Igc3ViamVjdGl2ZSksIG9ic2VydmUgZGF0YSwgYW5kIHJhdGlvbmFsbHkgdXBkYXRlIHlvdXIgYmVsaWVmcy4gVGhlIHJlc3VsdCBpcyBhIGZ1bGwgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIGZvciB0aGUgcGFyYW1ldGVyLg0KDQpgYGB7ciBiYXllc2lhbi11cGRhdGUsIGZpZy5jYXA9IkJheWVzaWFuIEluZmVyZW5jZTogVXBkYXRpbmcgUHJpb3IgQmVsaWVmIHdpdGggRGF0YSIsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTV9DQojIFNpbXVsYXRlIEJheWVzaWFuIHVwZGF0aW5nDQpzZXQuc2VlZCg3ODkpDQp4IDwtIHNlcSgwLCAxLCBsZW5ndGgub3V0ID0gMTAwKQ0KDQojIFByaW9yIChtb2RlcmF0ZWx5IGluZm9ybWVkKQ0KcHJpb3IgPC0gZGJldGEoeCwgOCwgOCkNCg0KIyBMaWtlbGlob29kIChkYXRhOiAxNSBzdWNjZXNzZXMgb3V0IG9mIDIwIHRyaWFscykNCmEgPC0gMTUNCmIgPC0gNQ0KbGlrZWxpaG9vZCA8LSBkYmV0YSh4LCBhLCBiKQ0KDQojIFBvc3Rlcmlvcg0KcG9zdGVyaW9yIDwtIGRiZXRhKHgsIDggKyBhLCA4ICsgYikNCg0KIyBQbG90DQpwbG90X2RmIDwtIGRhdGEuZnJhbWUoDQogIHggPSByZXAoeCwgMyksDQogIGRlbnNpdHkgPSBjKHByaW9yLCBsaWtlbGlob29kLCBwb3N0ZXJpb3IpLA0KICBkaXN0cmlidXRpb24gPSByZXAoYygiUHJpb3IiLCAiTGlrZWxpaG9vZCAoRGF0YSkiLCAiUG9zdGVyaW9yIiksIGVhY2ggPSBsZW5ndGgoeCkpDQopDQoNCmJheWVzIDwtIGdncGxvdChwbG90X2RmLCBhZXMoeCA9IHgsIHkgPSBkZW5zaXR5LCBjb2xvciA9IGRpc3RyaWJ1dGlvbiwgbGluZXR5cGUgPSBkaXN0cmlidXRpb24pKSArDQogIGdlb21fbGluZShzaXplID0gMS4yKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmlvciIgPSAiYmx1ZSIsICJMaWtlbGlob29kIChEYXRhKSIgPSAic3RlZWxibHVlIiwgIlBvc3RlcmlvciIgPSAicmVkIikpICsNCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoIlByaW9yIiA9ICJzb2xpZCIsICJMaWtlbGlob29kIChEYXRhKSIgPSAic29saWQiLCAiUG9zdGVyaW9yIiA9ICJzb2xpZCIpKSArDQogIGxhYnMoeCA9ICJQYXJhbWV0ZXIgKGUuZy4sIHN1Y2Nlc3MgcHJvYmFiaWxpdHkpIiwgeSA9ICJEZW5zaXR5IiwNCiAgICAgICAjdGl0bGUgPSAiQmF5ZXNpYW4gVXBkYXRpbmc6IFByaW9yIOKGkiBMaWtlbGlob29kIOKGkiBQb3N0ZXJpb3IiLA0KICAgICAgIGNvbG9yID0gIkRpc3RyaWJ1dGlvbiIsIGxpbmV0eXBlID0gIkRpc3RyaWJ1dGlvbiIpICsNCiAgdGhlbWUoDQogIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSA0MCwgciA9IDIwLCBiID0gMjAsIGwgPSAyMCwgdW5pdCA9ICJwdCIpLA0KICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICBtYXJnaW4gPSBtYXJnaW4odCA9IDIwLCBiID0gMCkpLCAgIyBUb3AgYW5kIGJvdHRvbSBtYXJnaW5zDQogIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDEwKSksDQogIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4ociA9IDEwKSkpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpnZ3Bsb3RseShiYXllcykNCmBgYA0KDQojIyMgKipVc2UtQ2FzZSBFeGFtcGxlczoqKg0KDQoxLiAgKipEcnVnIERldmVsb3BtZW50OioqIEVhcmx5IHRyaWFscyBwcm92aWRlIGEgKipwcmlvcioqIG9uIGEgZHJ1ZydzIGVmZmljYWN5LiBBIGxhcmdlciBQaGFzZSAzIHRyaWFsIHByb3ZpZGVzICoqZGF0YSoqLiAqKkJheWVzaWFuIGluZmVyZW5jZSoqIGNvbWJpbmVzIHRoZW0gdG8gcHJvZHVjZSBhICoqcG9zdGVyaW9yIHByb2JhYmlsaXR5KiogdGhhdCB0aGUgZHJ1ZyBleGNlZWRzIGEgbWluaW11bSBlZmZlY3RpdmVuZXNzIHRocmVzaG9sZOKAlGEgZGlyZWN0LCBpbnR1aXRpdmUgc3RhdGVtZW50IGZvciBkZWNpc2lvbi1tYWtlcnMuDQoNCg0KMi4gICoqTWFjaGluZSBMZWFybmluZy9TcGFtIEZpbHRlcmluZzoqKiBUaGUgZmlsdGVyIGhhcyBhICoqcHJpb3IgYmVsaWVmKiogYWJvdXQgdGhlIHByb2JhYmlsaXR5IGFuIGVtYWlsIGlzIHNwYW0uIEl0IHVwZGF0ZXMgdGhpcyBiZWxpZWYgYmFzZWQgb24gdGhlICoqZGF0YSoqIChwcmVzZW5jZSBvZiBrZXl3b3JkcyBsaWtlICJmcmVlLCIgIndpbm5lciIpLiBUaGUgKipwb3N0ZXJpb3IgcHJvYmFiaWxpdHkqKiBkaWN0YXRlcyB0aGUgInNwYW0vbm90IHNwYW0iIGNsYXNzaWZpY2F0aW9uLg0KDQoNCg0KIyBTeW50aGVzaXMgJiBDYXV0aW9ucw0KDQojIyBLZXkgUmVsYXRpb25zaGlwcyBhbmQgQ29tcGFyaXNvbnMNCg0KYGBge3IgY29tcGFyaXNvbi10YWJsZSwgZWNobz1GQUxTRX0NCiMgQ3JlYXRlIGEgY29tcGFyaXNvbiB0YWJsZQ0KY29tcGFyaXNvbl9kZiA8LSBkYXRhLmZyYW1lKA0KICBNZXRob2QgPSBjKCJDb25maWRlbmNlIEludGVydmFscyIsICJIeXBvdGhlc2lzIFRlc3RzIiwgIlJlZ3Jlc3Npb24gSW5mZXJlbmNlIiwgIkJheWVzaWFuIEluZmVyZW5jZSIpLA0KICBRdWVzdGlvbiA9IGMoIldoYXQgaXMgdGhlIHBsYXVzaWJsZSByYW5nZT8iLCAiSXMgdGhlcmUgZXZpZGVuY2UgYWdhaW5zdCBI4oKAPyIsICJXaGF0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2YXJpYWJsZXM/IiwgIldoYXQgc2hvdWxkIHdlIGJlbGlldmUgZ2l2ZW4gZGF0YSBhbmQgcHJpb3I/IiksDQogIE91dHB1dCA9IGMoIkludGVydmFsIGVzdGltYXRlIiwgInAtdmFsdWUsIGRlY2lzaW9uIiwgIlBhcmFtZXRlciBlc3RpbWF0ZXMgd2l0aCBDSXMiLCAiUG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiIpLA0KICBJbnRlcnByZXRhdGlvbiA9IGMoIkxvbmctcnVuIGZyZXF1ZW5jeSBvZiBjb3ZlcmFnZSIsICJQcm9iYWJpbGl0eSBvZiBkYXRhIGlmIEjigoAgdHJ1ZSIsICJFZmZlY3Qgc2l6ZSB3aXRoIHVuY2VydGFpbnR5IiwgIkRlZ3JlZSBvZiBiZWxpZWYgaW4gcGFyYW1ldGVyIHZhbHVlcyIpDQopDQoNCmtuaXRyOjprYWJsZShjb21wYXJpc29uX2RmLCANCiAgICAgICAgICAgICBjYXB0aW9uID0gIkNvbXBhcmlzb24gb2YgU3RhdGlzdGljYWwgSW5mZXJlbmNlIE1ldGhvZHMiLA0KICAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIk1ldGhvZCIsICJQcmltYXJ5IFF1ZXN0aW9uIiwgIk1haW4gT3V0cHV0IiwgIkludGVycHJldGF0aW9uIikpDQpgYGANCg0KKiAqKkVzdGltYXRpb24gKENJKSBhbmQgVGVzdGluZyAocC12YWx1ZXMpIGFyZSBsaW5rZWQ6KiogQSA5NSUgQ0kgdGhhdCAqKmV4Y2x1ZGVzKiogYSBudWxsIHZhbHVlIChsaWtlIDApIGNvcnJlc3BvbmRzIHRvIGEgaHlwb3RoZXNpcyB0ZXN0IHJlamVjdGluZyBI4oKAIGF0IM6xPTAuMDUuDQoNCmBgYHtyIGNpLXRlc3QtcmVsYXRpb25zaGlwLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCiMgRGVtb25zdHJhdGUgcmVsYXRpb25zaGlwIGJldHdlZW4gQ0kgYW5kIGh5cG90aGVzaXMgdGVzdA0KDQoNCiMgU2ltdWxhdGUgZGF0YSB3aGVyZSBDSSBleGNsdWRlcyAwDQpzZXQuc2VlZCgzMjEpDQpzYW1wbGVfZGF0YSA8LSBybm9ybSg1MCwgbWVhbiA9IDEuNSwgc2QgPSAyKQ0KDQojIFQtdGVzdA0KdGVzdF9yZXN1bHQgPC0gdC50ZXN0KHNhbXBsZV9kYXRhLCBtdSA9IDApDQpjaSA8LSB0ZXN0X3Jlc3VsdCRjb25mLmludA0KDQpjYXQoIiAgRGVtb25zdHJhdGlvbjogUmVsYXRpb25zaGlwIGJldHdlZW4gQ0kgYW5kIEh5cG90aGVzaXMgVGVzdFxuIiwNCiI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iLA0Kc3ByaW50ZigiXG4gIFNhbXBsZSBtZWFuOiAlLjNmXG4iLCBtZWFuKHNhbXBsZV9kYXRhKSksDQpzcHJpbnRmKCI5NSUlIENvbmZpZGVuY2UgSW50ZXJ2YWw6IFslLjNmLCAlLjNmXVxuIiwgY2lbMV0sIGNpWzJdKSwNCnNwcmludGYoInAtdmFsdWUgZm9yIEjigoA6IM68ID0gMDogJS40ZlxuIiwgdGVzdF9yZXN1bHQkcC52YWx1ZSksDQpzcHJpbnRmKCJcbiB3ZSAlcyB0aGUgbnVsbCBoeXBvdGhlc2lzIGF0IM6xPTAuMDUuXG4iLCANCiAgICAgICAgICAgIGlmZWxzZSh0ZXN0X3Jlc3VsdCRwLnZhbHVlIDwgMC4wNSwgIlJFSkVDVCIsICJGQUlMIFRPIFJFSkVDVCIpKSkNCmBgYA0KDQoNCiogKipTdGF0aXN0aWNhbCB2cy4gUHJhY3RpY2FsIFNpZ25pZmljYW5jZToqKiBBIHRlc3QgY2FuIGZpbmQgYSB0aW55LCAqKnN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQqKiBlZmZlY3QgKGR1ZSB0byBodWdlIHNhbXBsZSBzaXplKSwgYnV0IGl0IG1heSBiZSAqKnByYWN0aWNhbGx5IG1lYW5pbmdsZXNzKiouICoqQWx3YXlzIGxvb2sgYXQgdGhlIGVzdGltYXRlZCBlZmZlY3Qgc2l6ZSBhbmQgaXRzIENJLioqDQoNCiogKipJbmZlcmVuY2UgUmVxdWlyZXMgUmVwcmVzZW50YXRpdmUgRGF0YToqKiBHYXJiYWdlIGluLCBnYXJiYWdlIG91dC4gQmlhc2VkIHNhbXBsaW5nIGludmFsaWRhdGVzIGFueSBpbmZlcmVuY2UsIG5vIG1hdHRlciBob3cgc29waGlzdGljYXRlZC4NCg0KKiAqKkZyZXF1ZW50aXN0IChDSS9UZXN0cykgdnMuIEJheWVzaWFuIE1pbmRzZXQ6KiogIA0KICAqICoqRnJlcXVlbnRpc3Q6KiogUHJvYmFiaWxpdHkgPSBsb25nLXJ1biBmcmVxdWVuY3kuIFBhcmFtZXRlcnMgYXJlIGZpeGVkLCBkYXRhIGlzIHJhbmRvbS4gIA0KICAqICoqQmF5ZXNpYW46KiogUHJvYmFiaWxpdHkgPSBkZWdyZWUgb2YgYmVsaWVmLiBQYXJhbWV0ZXJzIGFyZSByYW5kb20sIGRhdGEgaXMgZml4ZWQuICANCiAgQm90aCBhcmUgcG93ZXJmdWwgdG9vbHM7IHRoZSBjaG9pY2Ugb2Z0ZW4gZGVwZW5kcyBvbiB0aGUgcXVlc3Rpb24sIGZpZWxkLCBhbmQgYXZhaWxhYmlsaXR5IG9mIHByaW9yIGluZm9ybWF0aW9uLg0KDQoNCiMgIEtleSBUYWtlYXdheQ0KDQpTdGF0aXN0aWNhbCBpbmZlcmVuY2UgaXMgdGhlICoqc2NpZW5jZSBvZiBkaXNjaXBsaW5lZCBsZWFybmluZyBmcm9tIGRhdGEgaW4gdGhlIGZhY2Ugb2YgdW5jZXJ0YWludHkuKiogSXQgbW92ZXMgdXMgZnJvbSBzaW1wbHkgZGVzY3JpYmluZyBvdXIgc2FtcGxlICgiVGhlIGF2ZXJhZ2UgaW4gb3VyIGRhdGEgd2FzIDEwIikgdG8gbWFraW5nICoqZ2VuZXJhbGl6YWJsZSBzdGF0ZW1lbnRzIHdpdGggcXVhbnRpZmllZCB1bmNlcnRhaW50eSoqICgiV2UgYXJlIDk1JSBjb25maWRlbnQgdGhlIHBvcHVsYXRpb24gYXZlcmFnZSBpcyBiZXR3ZWVuIDkgYW5kIDExIikuIA0KDQpNYXN0ZXJpbmcgdGhlIGJpZyBwaWN0dXJlIGFsbG93cyB5b3UgdG8gY2hvb3NlIHRoZSByaWdodCB0b29sIGZvciB0aGUgcXVlc3Rpb24gYXQgaGFuZCwgZnJvbSBlc3RpbWF0aW5nIGEgbWFya2V0IHNpemUsIHRvIHRlc3RpbmcgYSBuZXcgbWVkaWNhbCB0cmVhdG1lbnQsIHRvIHVwZGF0aW5nIGEgcmVjb21tZW5kYXRpb24gYWxnb3JpdGhtLg0KDQpgYGB7ciBmaW5hbC1zdW1tYXJ5LCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUaGUgSW5mZXJlbmNlIFByb2Nlc3M6IEZyb20gRGF0YSB0byBLbm93bGVkZ2UiLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00fQ0KIyBGaW5hbCBzdW1tYXJ5IHZpc3VhbGl6YXRpb24NCnByb2Nlc3Nfc3RlcHMgPC0gZGF0YS5mcmFtZSgNCiAgc3RlcCA9IDE6NSwNCiAgbGFiZWwgPSBjKCJEYXRhXG5Db2xsZWN0aW9uIiwgIk1vZGVsXG5TcGVjaWZpY2F0aW9uIiwgIkluZmVyZW5jZVxuUHJvY2VkdXJlIiwgIlVuY2VydGFpbnR5XG5RdWFudGlmaWNhdGlvbiIsICJLbm93bGVkZ2UgJlxuRGVjaXNpb24iKSwNCiAgeCA9IDE6NSwNCiAgeSA9IGMoMCwgMSwgMCwgMSwgMCkNCikNCg0KZ2dwbG90KHByb2Nlc3Nfc3RlcHMsIGFlcyh4ID0geCwgeSA9IHkpKSArDQogIGdlb21fcGF0aChjb2xvciA9ICJncmF5Iiwgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMzAsIGNvbG9yID0gIiMyYzNlNTAiLCBhbHBoYSA9IDAuOCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbGFiZWwpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzKSArDQogIGdlb21fdGV4dCh4ID0gMywgeSA9IDEuNSwgbGFiZWwgPSAiVGhlIFN0YXRpc3RpY2FsIEluZmVyZW5jZSBQcm9jZXNzIiwgDQogICAgICAgICAgICBzaXplID0gNSwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgeGxpbSgwLjUsIDUuNSkgKw0KICB5bGltKC0wLjUsIDEuOCkgKw0KICB0aGVtZV92b2lkKCkgKw0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAxLCAxLCAxKSwgImNtIikpDQpgYGANCg0KDQojIEZ1cnRoZXIgUmVzb3VyY2VzDQoNCiogKipSIFBhY2thZ2VzIGZvciBJbmZlcmVuY2U6KioNCiAgLSBCYXNpYzogYHN0YXRzYCAoYmFzZSBSKSwgYGluZmVyYCAodGlkeXZlcnNlIGFwcHJvYWNoKQ0KICAtIEJheWVzaWFuOiBgcnN0YW5gLCBgYnJtc2AsIGByc3RhbmFybWANCiAgLSBTcGVjaWFsaXplZDogYHN1cnZpdmFsYCwgYGxtZTRgLCBgbWdjdmANCg0KKiAqKlByYWN0aWNlIHdpdGg6KiogYGluZmVyOjpnZW5lcmF0ZSgpYCwgYGluZmVyOjpjYWxjdWxhdGUoKWAgZm9yIHNpbXVsYXRpb24tYmFzZWQgaW5mZXJlbmNlDQoNCiogKipOZXh0IFN0ZXBzOioqIEV4cGVyaW1lbnRhbCBkZXNpZ24sIHBvd2VyIGFuYWx5c2lzLCBtdWx0aXBsZSB0ZXN0aW5nIGNvcnJlY3Rpb25zLCBjYXVzYWwgaW5mZXJlbmNlIGZyYW1ld29ya3MuDQoNCioqUmVtZW1iZXI6KiogVGhlIG1hcCBpcyBub3QgdGhlIHRlcnJpdG9yeS4gU3RhdGlzdGljYWwgbW9kZWxzIGFyZSBzaW1wbGlmaWVkIHJlcHJlc2VudGF0aW9ucyBvZiByZWFsaXR54oCUcG93ZXJmdWwsIGJ1dCBhbHdheXMgaW1wZXJmZWN0Lg0K